from datetime import datetime
import logging
from controllers.errors.online_mall.order_errors import HOrderNotFoundError
from core.entities.account_role import AccountWrap
from extensions.ext_database import db
from flask_babel import _
from models.online_mall.order_settlement import MOrder, OrderStatus

class OrserService:
    @staticmethod
    def get_order_list(account:AccountWrap,args:dict)->dict:
        try:
            query = db.session.query(MOrder).filter(MOrder.tenant_id==account.current_tenant_id)
            total = 0
            has_more = False
            if 'id' in args and args['id']:
                query = query.filter(MOrder.id==args['id'])
                total = query.count()
            else:
                if 'shop_id' in args and args['shop_id']:
                    query = query.filter(MOrder.shop_id==args['shop_id'])
                if 'account_id' in args and args['account_id']:
                    query = query.filter(MOrder.account_id==args['account_id'])
                if 'order_no' in args and args['order_no']:
                    query = query.filter(MOrder.order_no.like(f"%{args['order_no']}%"))
                if 'status' in args and args['status']:
                    query = query.filter(MOrder.status==args['status'])
                if 'pay_type' in args and args['pay_type']:
                    query = query.filter(MOrder.pay_type==args['pay_type'])
                if 'dvy_flow_id' in args and args['dvy_flow_id']:
                    query = query.filter(MOrder.dvy_flow_id==args['dvy_flow_id'])
                if 'is_payed' in args and args['is_payed'] is not None:
                    query = query.filter(MOrder.is_payed==args['is_payed'])
                if 'del_status' in args and args['del_status']:
                    query = query.filter(MOrder.del_status==args['del_status'])
                if 'refund_status' in args and args['refund_status']:
                    query = query.filter(MOrder.refund_status==args['refund_status'])
                if 'order_type' in args and args['order_type']:
                    query = query.filter(MOrder.order_type==args['order_type'])
                if 'close_type' in args and args['close_type']:
                    query = query.filter(MOrder.close_type==args['close_type'])
                total = query.count()
                if 'page' in args and args['page']>0 and 'page_size' in args and args['page_size']>0:
                    query = query.offset((args['page']-1)*args['page_size']).limit(args['page_size'])
                    has_more = total > args['page']*args['page_size']
            data = query.order_by(MOrder.create_at.desc()).all()
            return {
                "total":total,
                "has_more":has_more,
                "data":data
            }
        except Exception as e:
            logging.error(e)
            return {
                "total":0,
                "has_more":False,
                "data":[],
                "message":str(e)
            }

    @staticmethod
    def deliveried_orders(account:AccountWrap,shop_id:str|None,start:datetime|None,end:datetime|None,page:int=-1,page_size:int=-1)->dict:
        try:
            query = db.session.query(MOrder).filter(MOrder.tenant_id==account.current_tenant_id,MOrder.status==OrderStatus.WAIT_DELIVER.value)
            total = 0
            has_more = False
            if shop_id:
                query = query.filter(MOrder.shop_id==shop_id)
            if start:
                query = query.filter(MOrder.create_at>=start)
            if end:
                query = query.filter(MOrder.create_at<=end)
            total = query.count()
            if page>0 and page_size>0:
                query = query.offset(page_size*(page-1)).limit(page_size)
                has_more = total > page_size*page
            data = query.order_by(MOrder.create_at.desc()).all()
            return {
                "total": total,
                "has_more":has_more,
                "data":data
            }
        except Exception as e:
            logging.error(e)
            return {
                "total":0,
                "has_more":False,
                "data":[],
                "message":str(e)
            }
        
    @staticmethod
    def sold_orders(account:AccountWrap,shop_id:str|None,start:datetime|None,end:datetime|None,page:int=-1,page_size:int=-1)->dict:
        try:
            query = db.session.query(MOrder).filter(MOrder.tenant_id==account.current_tenant_id,MOrder.is_payed==True,MOrder.dvy_at==None)
            total = 0
            has_more = False
            if shop_id:
                query = query.filter(MOrder.shop_id==shop_id)
            if start:
                query = query.filter(MOrder.create_at>=start)
            if end:
                query = query.filter(MOrder.create_at<=end)
            total = query.count()
            if page>0 and page_size>0:
                query = query.offset(page_size*(page-1)).limit(page_size)
                has_more = total > page_size*page
            data = query.order_by(MOrder.create_at.desc()).all()
            return {
                "total": total,
                "has_more":has_more,
                "data":data
            }
        except Exception as e:
            logging.error(e)
            return {
                "total":0,
                "has_more":False,
                "data":[],
                "message":str(e)
            }
            
    @staticmethod
    def get_order_by_order_no(account:AccountWrap,order_no:str)->MOrder|None:
        try:
            return db.session.query(MOrder).filter(MOrder.tenant_id==account.current_tenant_id,MOrder.order_no==order_no).first()
        except Exception as e:
            logging.error(e)
        return None
        
    @staticmethod
    def delivery_order(account:AccountWrap,order_no,dvy_id,dvy_flow_id)->MOrder:
        try:
            order = db.session.query(MOrder).filter(MOrder.order_no==order_no).first()
            if not order:
                raise HOrderNotFoundError(order_no)
            order.dvy_at = datetime.now()
            order.dvy_id = dvy_id
            order.dvy_flow_id = dvy_flow_id
            order.status = OrderStatus.WAIT_RECEIVE.value
            db.session.commit()
            return order
        except HOrderNotFoundError as e:
            db.session.rollback()
            raise e
        except Exception as e:
            db.session.rollback()
            raise e
            